﻿/*****************************************************
**Copyright(C), 2021-2022, Ciqtek Technology.
**Version:     1.0
**Author:      dingyy
**Date:        2022/01/19
**Description: 该模块为扩展类集合，派生自QT，一般以Ciq开头
*****************************************************/

#ifndef UTILS_H
#define UTILS_H

#include "Base/NameSpace.h"
#include "common_global.h"
#include <QTime>
#include <QSettings>
#include <QDoubleValidator>
#include <QMap>
#include <QTimer>
#include <QMutex>

BEGIN_NAMESPACE_CIQTEK

template<typename K, typename D>
class BlockNoRepeatList;
class PriorityThread;

class COMMON_EXPORT CiqTime : public QTime
{
public:
	/**
	 * @brief  CiqTime 
	 * @return  
	 */
	CiqTime();

    /**
     * @brief  ~CiqTime 
     * @return  
     */
	virtual ~CiqTime();

public:
    /**
     * @brief  IsGreaterThan 超过规定时间返回true，否则返回false
     * @param  time 规定时间
     * @return bool 
     */
	bool isGreaterThan(const uint32_t time);

    /**
     * @brief  IsStart 定时器是否开启
     * @return bool 
     */
	bool isStart();

    /**
     * @brief  restart 重启定时器
     * @return void 
     */
	void restart();

    /**
     * @brief  start 开启定时器
     * @return void 
     */
	void start();

    /**
     * @brief  stop 关闭定时器
     * @return void 
     */
	void stop();

private:
	/**定时器开关标志
	 */
	bool m_isStart;
};

//////////////////////////////////////////////////////////////////////////

class COMMON_EXPORT CiqSettings : public QSettings
{
	Q_OBJECT

public:
    /**
     * @brief  指令数据项
     */
    struct CmdItemData
    {
        QString key;            ///< key
        QVariant value;         ///< value
        bool isForce;           ///< 是否强制写
    };

public:
    /**
     * @brief  CiqSettings 构造函数
     * @param  scope
     * @param  parent
     * @return
     */
    CiqSettings(QSettings::Scope scope, QObject *parent = nullptr);

    /**
     * @brief  CiqSettings 构造函数
     * @param  parent
     * @return
     */
    CiqSettings(QObject *parent = nullptr);

    /**
     * @brief  CiqSettings 构造函数
     * @param  fileName
     * @param  format
     * @param  parent
     * @return
     */
    CiqSettings(const QString &fileName, QSettings::Format format, QObject *parent = nullptr);

    /**
     * @brief  CiqSettings 构造函数
     * @param  format 
     * @param  scope 
     * @param  organization 
     * @param  application 
     * @param  parent 
     * @return  
     */
    CiqSettings(QSettings::Format format, QSettings::Scope scope, const QString &organization, const QString &application = QString(), QObject *parent = nullptr);
    
    /**
     * @brief  CiqSettings 构造函数
     * @param  scope 
     * @param  organization 
     * @param  application 
     * @param  parent 
     * @return  
     */
    CiqSettings(QSettings::Scope scope, const QString &organization, const QString &application = QString(), QObject *parent = nullptr);
    
    /**
     * @brief  CiqSettings 构造函数
     * @param  organization 
     * @param  application 
     * @param  parent 
     * @return  
     */
    CiqSettings(const QString &organization, const QString &application = QString(), QObject *parent = nullptr);

    /**
     * @brief  ~CiqSettings 析构函数
     * @return
     */
    virtual ~CiqSettings();

public:
    /**
     * @brief  setValue 设置值
     * @param  key
     * @param  value
     * @param  isForce
     * @return void
     */
    void setValue(const QString& key, const QVariant& value, const bool isForce = true);

    /**
     * @brief  setValueASync 设置值-异步
     * @param  key
     * @param  value
     * @param  isForce
     * @return void
     */
    void setValueAsync(const QString& key, const QVariant& value, const bool isForce = true);

    /**
     * @brief  setValue 设置值
     * @param  group 
     * @param  key 
     * @param  value 
     * @param  isForce
     * @return void 
     */
    void setValue(const QString &group, const QString &key, const QVariant &value, const bool isForce = true);

    /**
     * @brief  setValue 设置值-异步
     * @param  group
     * @param  key
     * @param  value
     * @param  isForce
     * @return void
     */
    void setValueAsync(const QString& group, const QString& key, const QVariant& value, const bool isForce = true);

protected:
	/**
	 * @brief  init 初始化
	 * @return void 
	 */
	void init();

    /**
     * @brief  event 
     * @param  event 
     * @return bool 
     */
    bool event(QEvent *event);

private:
    /**
     * @brief   process 线程函数
     * @return  void
     */
    void run();

private:
    /** 线程停止标记
     */
    std::atomic_bool m_stopFlag;

    /** 工作线程
     */
    PriorityThread * m_workerThread;

    /** 无重复数据链表
     */
    BlockNoRepeatList<QString, CmdItemData> * m_noRepeatList;
};

//////////////////////////////////////////////////////////////////////////


class COMMON_EXPORT DBValidator : public QDoubleValidator
{
public:
    DBValidator(double bottom, double top, int decimals, QObject * parent) :
        QDoubleValidator(bottom, top, decimals, parent)
    {
    }

    QDoubleValidator::State validate(QString &s, int &i) const
    {
        if (s.isEmpty() || s == "-") {
            return QDoubleValidator::Intermediate;
        }

        QChar decimalPoint = locale().decimalPoint();

        if (s.indexOf(decimalPoint) != -1) {
            int charsAfterPoint = s.length() - s.indexOf(decimalPoint) - 1;

            if (charsAfterPoint > decimals()) {
                return QDoubleValidator::Invalid;
            }
        }

        bool ok;
        double d = locale().toDouble(s, &ok);

        if (ok && d >= bottom() && d <= top()) {
            return QDoubleValidator::Acceptable;
        }
        else {
            return QDoubleValidator::Invalid;
        }
    }
};

END_NAMESPACE_CIQTEK

#endif // UTILS_H
